home *** CD-ROM | disk | FTP | other *** search
/ Large Pack of OldSkool DOS MOD Trackers / package_16-january-2001.zip / Effects / cheapo amp.cpp < prev    next >
C/C++ Source or Header  |  2000-10-14  |  9KB  |  399 lines

  1. // Copyright (C) Mikko Apo (apo@iki.fi)
  2. // The following code may be used to write free software
  3. // if credit is given to the original author.
  4. // Using it for anything else is not allowed without permission
  5. // from the author.
  6.  
  7.  
  8. #include <stdlib.h>
  9. #include <time.h>
  10. #include <math.h>
  11. #include <string.h>
  12. #include "../mdk.h"
  13.  
  14. #define miCOMMAND_STRING "About..."
  15. #define miMACHINE_NAME "cheapo amp"
  16. #define miSHORT_NAME "ch.amp"
  17. #define miMACHINE_AUTHOR "Mikko Apo (apo@iki.fi)"
  18. #define miMAX_TRACKS        0
  19. #define miMIN_TRACKS        0
  20. #define miNUMGLOBALPARAMETERS    4
  21. #define miNUMTRACKPARAMETERS    0
  22. #define miNUMATTRIBUTES    7
  23. #define miVERSION "1.0"
  24.  
  25. //    Parameters
  26.  
  27. CMachineParameter const paraMaxGain = 
  28. { pt_word, "Max Gain","Max Gain in dB [0=-96.0dB, 960=0.0dB, 1280=+32.0dB]",0,1280,0xffff,MPF_STATE,960};
  29.  
  30. CMachineParameter const paraGain = 
  31. { pt_word, "Gain","Gain in %",0,1000,0xffff,MPF_STATE,1000};
  32.  
  33. CMachineParameter const paraMute = 
  34. { pt_switch, "Mute","",0,1,SWITCH_NO,MPF_STATE,0};
  35.  
  36. CMachineParameter const paraInertia = 
  37. { pt_byte, "Inertia","Inertia",0,0xfe,0xff,MPF_STATE,10 };
  38.  
  39. // List of all parameters, track parameters last
  40.  
  41. CMachineParameter const *pParameters[] = 
  42. { ¶MaxGain,¶Gain,¶Mute,¶Inertia};
  43.  
  44. // Attributes
  45.  
  46. CMachineAttribute const attrMuteInertia = { "Inertia controlled Mute [0=no]" ,0,1,0 };
  47. CMachineAttribute const attrMuteIn = { "Mute start fade in [ms]" ,0,1000,50 };
  48. CMachineAttribute const attrMuteOut = { "Mute end fade out [ms]" ,0,1000,50 };
  49. CMachineAttribute const attrMinDB = { "M.Gain neg. dB [min]" ,0,128,96 };
  50. CMachineAttribute const attrMaxDB = { "M.Gain pos. dB [max]" ,0,128,32 };
  51. CMachineAttribute const attrMinPercent = { "Min Gain %" ,0,1000,0 };
  52. CMachineAttribute const attrMaxPercent = { "Max Gain %" ,0,1000,100 };
  53.  
  54. // List of all attributes
  55.  
  56. CMachineAttribute const *pAttributes[] =
  57. { &attrMuteInertia,&attrMuteIn,&attrMuteOut,&attrMinDB,&attrMaxDB,&attrMinPercent,&attrMaxPercent };
  58.  
  59. #pragma pack(1)
  60.  
  61. class gvals
  62. {
  63. public:
  64.     word maxgain;
  65.     word gain;
  66.     byte mute;
  67.     byte inertia;
  68. };
  69.  
  70. class avals
  71. {
  72. public:
  73.     int muteinertia;
  74.     int mutein;
  75.     int muteout;
  76.     int dbmin;
  77.     int dbmax;
  78.     int percentmin;
  79.     int percentmax;
  80. };
  81.  
  82. #pragma pack()
  83.  
  84. // Machine's info
  85.  
  86. CMachineInfo const MacInfo = 
  87. {
  88.     MT_EFFECT,MI_VERSION,MIF_DOES_INPUT_MIXING,miMIN_TRACKS,miMAX_TRACKS,
  89.     miNUMGLOBALPARAMETERS,miNUMTRACKPARAMETERS,pParameters,miNUMATTRIBUTES,pAttributes,
  90. #ifdef _DEBUG
  91.     miMACHINE_NAME" [DEBUG]"
  92. #else
  93.     miMACHINE_NAME
  94. #endif
  95.     ,miSHORT_NAME,miMACHINE_AUTHOR,miCOMMAND_STRING
  96. };
  97.  
  98.  
  99. class miex : public CMDKMachineInterfaceEx
  100. {
  101.  
  102. };
  103.  
  104. class mi : public CMDKMachineInterface
  105. {
  106. public:
  107.     mi();
  108.  
  109.     public:
  110.     virtual void Command(int const i);
  111.     virtual void Tick();
  112.     virtual char const *DescribeValue(int const param, int const value);
  113.  
  114.     virtual void MDKInit(CMachineDataInput * const pi);
  115.     virtual bool MDKWork(float *psamples, int numsamples, int const mode);
  116.     virtual bool MDKWorkStereo(float *psamples, int numsamples, int const mode);
  117.     virtual void MDKSave(CMachineDataOutput * const po) { }
  118.  
  119.     virtual CMDKMachineInterfaceEx *GetEx() { return &ex; }
  120.     virtual void OutputModeChanged(bool stereo) {}
  121.  
  122.     virtual void AttributesChanged();
  123.  
  124.     public:
  125.     miex ex;
  126.     gvals gval;
  127.     avals aval;
  128.  
  129. private:
  130.  
  131.     double valMaxGain;
  132.     float valGain;
  133.     bool valMute;
  134.     long valInertia;
  135.     long valMuteInertia,valMuteIn,valMuteOut,valDBMin,valDBMax,valPercentMin,valPercentMax;
  136.     double amp_current;
  137.     double amp_dest,amp_inc;    
  138.     long inc_counter;
  139.     bool inertia;
  140.     bool firsttime;
  141. };
  142.  
  143.  
  144. DLL_EXPORTS
  145.  
  146. mi::mi()
  147. {
  148.     GlobalVals = &gval;
  149.     AttrVals = (int *)&aval;
  150. }
  151.  
  152. void mi::Command(int const i)
  153. {
  154.     switch(i)
  155.     {
  156.     case 0:
  157.         pCB->MessageBox(miMACHINE_NAME"\n\nBuild date: "__DATE__"\nVersion: "miVERSION"\nCoded by: "miMACHINE_AUTHOR"\n\nCheck out http://www.iki.fi/apo/buzz/\nfor more buzz stuff.\n\nExcellent skin made by Hymax.");
  158.         break;
  159.     }
  160. }
  161.  
  162. void mi::AttributesChanged()
  163. {
  164.     long tmp;
  165.     valMuteInertia=aval.muteinertia;
  166.     valMuteIn=(int)((aval.mutein*pMasterInfo->SamplesPerSec)/1000);
  167.     valMuteOut=(int)((aval.muteout*pMasterInfo->SamplesPerSec)/1000);
  168.     valDBMin=aval.dbmin;
  169.     valDBMax=aval.dbmax;
  170.     valPercentMin=aval.percentmin;
  171.     valPercentMax=aval.percentmax;
  172.     if(valPercentMin>valPercentMax)
  173.     {
  174.         tmp=valPercentMin;
  175.         valPercentMin=valPercentMax;
  176.         valPercentMax=tmp;
  177.     }
  178.     if(valPercentMin==valPercentMax)
  179.     {
  180.         valPercentMin=attrMinPercent.DefValue;
  181.         valPercentMax=attrMaxPercent.DefValue;
  182.     }
  183.     if(!valDBMin&&!valDBMax)
  184.     {
  185.         valDBMin=attrMinDB.DefValue;
  186.         valDBMax=attrMaxDB.DefValue;
  187.     }
  188.  
  189. }
  190.  
  191. float inertiatime(int value)
  192. {
  193.     double tmp;
  194.     tmp=(float)(value/10.0);
  195. #define vr(x,y,z) if(value>(x)) tmp=(float)((y)+(z)*(value-(x)))
  196.     vr(80,8,1);
  197.     vr(136,64,2);
  198.     vr(232,256,64);
  199.     vr(236,512,128);
  200.     vr(240,1024,256);
  201.     vr(244,2048,512);
  202.     vr(248,4096,1024);
  203. #undef vr
  204.     return (float)tmp;
  205. }
  206.  
  207. char const *mi::DescribeValue(int const param, int const value)
  208. {
  209.     static char txt[100];
  210.  
  211.     if(!param) sprintf(txt,"%-2.1f dB",(float) (value*(valDBMin+valDBMax)/1280.0-valDBMin) );
  212.     if(param==1) sprintf(txt,"%.1f %%",value*(aval.percentmax-aval.percentmin)/1000.0+aval.percentmin);
  213.     if(param==2) sprintf(txt,"%s",value?"on":"off");
  214.     if(param==3) sprintf(txt,"%.1f ticks",inertiatime(value));
  215.  
  216.     return txt;
  217. }
  218.  
  219. #define calc_maxgain(value) pow(10, ( (value*(valDBMin+valDBMax)/1280.0-valDBMin) * 0.05))
  220. #define calc_gain(value) (float)(((value)*(aval.percentmax-aval.percentmin)/1000.0+aval.percentmin)/100.0)
  221.  
  222. void mi::MDKInit(CMachineDataInput * const pi)
  223. {
  224.     valMaxGain=calc_maxgain(paraMaxGain.DefValue);
  225.     valGain=calc_gain(paraGain.DefValue);
  226.     valMute=(paraMute.DefValue)?true:false;
  227.     valInertia=(int)(inertiatime(paraInertia.DefValue)*pMasterInfo->SamplesPerTick);
  228.     AttributesChanged();
  229.     amp_current=1.0;
  230.     inertia=false;
  231.     firsttime=true;
  232. }
  233.  
  234.  
  235. void mi::Tick()
  236. {
  237.   bool gainchanged=false,mutechanged=false;
  238.   if (gval.maxgain != paraMaxGain.NoValue)
  239.   {
  240.     valMaxGain=calc_maxgain(gval.maxgain);
  241.     gainchanged=true;
  242.   }
  243.   if (gval.gain != paraGain.NoValue)
  244.   {
  245.     valGain=calc_gain(gval.gain);
  246.     gainchanged=true;
  247.   }
  248.   if (gval.mute != paraMute.NoValue)
  249.   {
  250.     bool tmpmute=(gval.mute)?true:false;
  251.     if(tmpmute&&!valMute||!tmpmute&&valMute)
  252.     {
  253.         mutechanged=true;
  254.     }
  255.     valMute=tmpmute;
  256.   }
  257.   if(gval.inertia != paraInertia.NoValue)
  258.   {
  259.       valInertia=(int)(inertiatime(gval.inertia)*pMasterInfo->SamplesPerTick);
  260.   }
  261.   if(mutechanged)
  262.   {
  263.       if(valMute)
  264.       {
  265.           amp_dest=0.0;
  266.           inc_counter=valMuteInertia?valInertia:valMuteIn;
  267.       } else
  268.       {
  269.           amp_dest=valGain*valMaxGain;
  270.           inc_counter=valMuteInertia?valInertia:valMuteOut;
  271.       }
  272.   } else if(gainchanged)
  273.   {
  274.       if(valMute)
  275.       {
  276.           gainchanged=false;
  277.       } else
  278.       {
  279.         amp_dest=valGain*valMaxGain;
  280.         inc_counter=valInertia;
  281.       }
  282.   }
  283.   if(firsttime)
  284.   {
  285.       amp_current=1.0;
  286.       inertia=false;
  287.       firsttime=false;
  288.   } else
  289.   {
  290.     if(mutechanged||gainchanged)
  291.     {
  292.           amp_inc=(amp_dest-amp_current)/inc_counter;
  293.           inertia=true;
  294.       }
  295.   }
  296.  
  297. // update inertia counters
  298. #define upd_inertia    if(inertia) { \
  299.             inc_counter-=numsamples; \
  300.             if(inc_counter>0){ \
  301.               amp_current=amp_current+amp_inc*numsamples; \
  302.             } else { \
  303.                 inertia=false; \
  304.                 amp_current=amp_dest; \
  305.             } \
  306.         }
  307.  
  308. bool mi::MDKWorkStereo(float *psamples, int numsamples, int const mode)
  309. {
  310.     if (mode==WM_NOIO)
  311.     {
  312.         return false;
  313.     }
  314.  
  315.     if (mode==WM_WRITE) // no sound coming in
  316.     {
  317.         // if there's inertia, update counters
  318.         upd_inertia;
  319.         return false;
  320.     }
  321.  
  322.     if (mode == WM_READ)        // <thru>
  323.     {
  324.         // if there's inertia, update counters
  325.         upd_inertia;
  326.         return true;
  327.     }
  328.  
  329.     // no sound coming out if amp_current = 0 and there's no inertia
  330.     if(amp_current=0.0&&!inertia) return false;
  331.  
  332.     do 
  333.     {
  334.         if(inertia)
  335.         {
  336.             inc_counter--;
  337.             if(inc_counter>0)
  338.             {
  339.               amp_current=amp_current+amp_inc;
  340.             } else
  341.             {
  342.                 inertia=false;
  343.                 amp_current=amp_dest;
  344.             }
  345.         }
  346.         psamples[0]=(float)(amp_current*psamples[0]);
  347.         psamples[1]=(float)(amp_current*psamples[1]);
  348.         psamples+=2;
  349.     } while(--numsamples);
  350.  
  351.     return true;
  352. }
  353. bool mi::MDKWork(float *psamples, int numsamples, int const mode)
  354. {
  355.     if (mode==WM_NOIO)
  356.     {
  357.         return false;
  358.     }
  359.  
  360.     if (mode==WM_WRITE) // no sound coming in
  361.     {
  362.         // if there's inertia, update counters
  363.         upd_inertia;
  364.         return false;
  365.     }
  366.  
  367.     if (mode == WM_READ)        // <thru>
  368.     {
  369.         // if there's inertia, update counters
  370.         upd_inertia;
  371.         return true;
  372.     }
  373.  
  374.     // no sound coming out if amp_current = 0 and there's no inertia
  375.     if(amp_current==0.0&&!inertia) return false;
  376.  
  377.     do 
  378.     {
  379.         if(inertia)
  380.         {
  381.             inc_counter--;
  382.             if(inc_counter>0)
  383.             {
  384.               amp_current+=amp_inc;
  385.             } else
  386.             {
  387.                 inertia=false;
  388.                 amp_current=amp_dest;
  389.             }
  390.         }
  391.         psamples[0]=(float)(psamples[0]*amp_current);
  392.         psamples++;
  393.     } while(--numsamples);
  394.  
  395.     return true;
  396. }
  397.  
  398. #undef upd_inertia